@import "./mixin.less";

@field-width: 350px;
@grid-spacing: 15px;
@grid-row-cells: 4; //行或列数
@tile-size: ((@field-width - @grid-spacing * (@grid-row-cells + 1)) / @grid-row-cells);
@tile-border-radius: 3px; //砖边框圆角

@mobile-threshold: @field-width + 20px;

@text-color: #776e65;
@bright-text-color: #f9f6f2;

@tile-color: #eee4da;
@tile-gold-color: #edc22e;
@tile-gold-glow-color: lighten(@tile-gold-color, 15%);

@game-container-margin-top: 40px;
@game-container-background: #bbada0;

@transition-speed: 100ms;

// less定义mixin
.button {
  display: inline-block;
  background: darken(@game-container-background, 20%);
  border-radius: 3px;
  padding: 0 20px;
  text-decoration: none;
  color: @bright-text-color;
  height: 40px;
  line-height: 42px;
}

@keyframes fade-in {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

@keyframes move-up {
  0% {
    top: 25px;
    opacity: 1;
  }

  100% {
    top: -50px;
    opacity: 0;
  }
}

@keyframes appear {
  0% {
    opacity: 0;
    .transform(scale(0));
  }

  100% {
    opacity: 1;
    .transform(scale(1));
  }
}

@keyframes pop {
  0% {
    .transform(scale(0));
  }

  50% {
    .transform(scale(1.2));
  }

  100% {
    .transform(scale(1));
  }
}

/*
模块定位用float
*/

.container {
  width: @field-width;
  margin: 0 auto;

  .heading {
    .clearfix();

    .title {
      font-size: 50px;
      font-weight: bold;
      margin: 0;
      display: block;
      float: left;
    }

    // 计算得分区域
    .scores-container {
      float: right;
      text-align: right;

      .score-container,
      .best-container {
        @height: 25px;

        position: relative;
        display: inline-block;
        background: @game-container-background;
        padding: 15px 25px;
        font-size: @height;
        height: @height;
        line-height: @height + 22px;
        font-weight: bold;
        border-radius: 3px;
        color: white;
        margin-top: 8px;
        margin-left: 8px;
        text-align: center;

        &:after {
          position: absolute;
          width: 100%;
          top: 10px;
          left: 0;
          text-transform: uppercase; //文本转大写
          font-size: 13px;
          line-height: 13px;
          text-align: center;
          color: @tile-color;
        }

        .score-addition {
          position: absolute;
          right: 30px;
          color: red;
          font-size: @height;
          line-height: @height;
          font-weight: bold;
          color: rgba(@text-color, 0.9);
          z-index: 100;
          .animation(move-up 600ms ease-in);
          .animation-fill-mode(both);
        }
      }

      .score-container:after {
        content: "Score";
      }

      .best-container:after {
        content: "Best";
      }
    }
  }

  // 开始游戏按钮
  .above-game {
    display: flex;
    justify-content: space-between;
    align-items: center;

    .game-intro {
      width: 60%;
      line-height: 42px;
      margin-bottom: 0;
    }

    .restart-button {
      .button();
      display: block;
      text-align: center;
    }
  }
}

// End of game-field mixin
.game-container {
  margin-top: @game-container-margin-top;
  position: relative;
  padding: @grid-spacing;

  cursor: default;
  -webkit-touch-callout: none;
  -ms-touch-callout: none;

  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;

  -ms-touch-action: none;
  touch-action: none;

  background: @game-container-background;
  border-radius: @tile-border-radius * 2;
  width: @field-width;
  height: @field-width;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;

  .game-message {
    display: none;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: rgba(@tile-color, 0.5);
    z-index: 100;
    text-align: center;
    .animation(fade-in 800ms ease @transition-speed * 12);
    .animation-fill-mode(both);

    p {
      font-size: 60px;
      font-weight: bold;
      height: 60px;
      line-height: 60px;
      margin-top: 222px;
    }

    .lower {
      display: block;
      margin-top: 59px;
    }

    a {
      .button();
      margin-left: 9px;

      &.keep-playing-button {
        display: none;
      }
    }

    &.game-won {
      background: rgba(@tile-gold-color, 0.5);
      color: @bright-text-color;

      a.keep-playing-button {
        display: inline-block;
      }
    }

    &.game-won,
    &.game-over {
      display: block;
    }
  }

  .grid-container {
    position: absolute;
    z-index: 1;

    .grid-row {
      margin-bottom: @grid-spacing;

      &:last-child {
        margin-bottom: 0;
      }

      &:after {
        content: "";
        display: block;
        clear: both;
      }

      .grid-cell {
        width: @tile-size;
        height: @tile-size;
        margin-right: @grid-spacing;
        float: left;

        border-radius: @tile-border-radius;

        background: rgba(@tile-color, 0.35);

        &:last-child {
          margin-right: 0;
        }
      }
    }
  }

  .tile-container {
    position: absolute;
    z-index: 2;

    .tile {
      position: absolute; // Makes transforms relative to the top-left corner
      .transition(@transition-speed ease-in-out);
      -webkit-transition-property: -webkit-transform;
      -moz-transition-property: -moz-transform;
      transition-property: transform;

      @base: 2; // 底数
      @exponent: 1; // 幂数
      @limit: 11; // 2^11 = 2048

      // Colors for all 11 states, false = no special color
      @special-colors: false false,
        // 2
        false false,
        // 4
        #f78e48 true,
        // 8
        #fc5e2e true,
        // 16
        #ff3333 true,
        // 32
        #ff0000 true,
        // 64
        false true,
        // 128
        false true,
        // 256
        false true,
        // 512
        false true,
        // 1024
        false true; // 2048

      &.tile-super .tile-inner {
        color: @bright-text-color;
        background: mix(#333, @tile-gold-color, 95%);

        font-size: 30px;
      }

      .tile-inner {
        width: @tile-size;
        height: @tile-size;
        line-height: @tile-size;
        border-radius: @tile-border-radius;
        background: @tile-color;
        text-align: center;
        font-weight: bold;
        z-index: 10;
        font-size: 55px;
      }

      // 指数计算背景颜色、发光效果和字体大小
      // Less 不支持 @while 和 @for 循环，但可以通过 递归 Mixin 和 嵌套规则 实现类似功能。 @if也不支持使用 & when not
      .build-tile-colors(@exponent, @limit) when (@exponent <= @limit) {
        @power: pow(@base, @exponent); //计算一个数的幂

        &.tile-@{power} .tile-inner {
          @gold-percent: ((@exponent - 1) / (@limit - 1) * 100); //根据指数计算金色背景的百分比
          @mixed-background: mix(
            @tile-gold-color,
            @tile-color,
            @gold-percent
          ); //混合金色和基础颜色，（color1,color2,percent）返回一个新的颜色值
          @nth-color: extract(
            @special-colors,
            @exponent
          ); // 获取列表第n个元素 @list: 10px, 20px, 30px, 40px; @third-item: nth(@list, 3); // 输出 30px

          @special-background: extract(@nth-color, 1); //特殊颜色列表，用于覆盖默认颜色
          @bright-color: extract(@nth-color, 2);

          & when (@special-background) {
            @mixed-background: mix(@special-background, @mixed-background, 55%);
          }

          & when (@bright-color) {
            color: @bright-text-color;
          }

          // 设置背景
          background: @mixed-background;

          // 添加发光效果，根据发光指数计算,指数越大发光越亮
          @glow-opacity: max(@exponent - 4, 0) / (@limit - 4);

          & when (@special-background = null) {
            box-shadow: 0 0 30px 10px rgba(@tile-gold-glow-color, @glow-opacity / 1.8),
              inset 0 0 0 1px rgba(white, @glow-opacity / 3);
          }

          // 调整字体大小
          & when (@power >= 100) and (@power < 1000) {
            font-size: 45px;

            // 媒体查询
            @media (max-width: @mobile-threshold) {
              font-size: 25px;
            }
          }

          & when (@power >= 1000) {
            font-size: 35px;

            @media (max-width: @mobile-threshold) {
              font-size: 15px;
            }
          }
        }

        // 递归调用，指数+1
        .build-tile-colors(@exponent + 1, @limit);
      }

      // 调用生成函数
      .build-tile-colors(@exponent, @limit);

      // 计算砖位置，两层循环
      .build-position-classes(@x, @y, @grid-row-cells) when (@x <= @grid-row-cells) {
        // 外层循环
        & when (@y <= @grid-row-cells) {
          // 内层循环
          // Less 不支持直接在类名中使用变量插值,使用~生成动态选择器
          @selector: ~"&.tile-position-@{x}-@{y}";
          @{selector} {
            @xPos: floor((@tile-size + @grid-spacing) * (@x - 1));
            @yPos: floor((@tile-size + @grid-spacing) * (@y - 1));
            .transform(translate(@xPos, @yPos));
          }

          // 递归调用
          .build-position-classes(@x, @y + 1, @grid-row-cells);
        }

        // 递归调用
        .build-position-classes(@x + 1, 1, @grid-row-cells);
      }

      .build-position-classes(1, 1, @grid-row-cells);
    }
  }
}
